package com.geng.invoker;


import com.geng.connect.IConnectStrategy;
import com.geng.dto.MyRequest;
import com.geng.dto.MyResponse;
import com.geng.dto.ProviderService;
import com.geng.filter.Filter;
import com.geng.filter.FilterChain;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.Iterator;
import java.util.List;
import java.util.ServiceLoader;
import java.util.UUID;


/**
 * @author geng
 *
 *   引用的动态代理
 *
 */
public class InvokerProxy implements InvocationHandler {

    /**
     * 需要调用的服务的接口
     */
    private Class<?> targetInterface;
    /**
     * 超时时间
     */
    private int consumeTimeout;

    /**
     * 连接策略
     */
    private IConnectStrategy connectStrategy;

    /*  *//**
     * 所有的 filter
     * @param targetInterface
     * @param consumeTimeout
     * @param clusterStrategy
     */
    private static List<Filter> filterList = new ArrayList<>();


    //jdk的spi机制
    static {
        ServiceLoader<Filter> serviceLoader = ServiceLoader.load(Filter.class);
        Iterator<Filter> iterator = serviceLoader.iterator();
        while (iterator.hasNext()) {
            filterList.add(iterator.next());
        }
        Collections.sort(filterList, new Comparator<Filter>() {
            @Override
            public int compare(Filter o1, Filter o2) {
                if (o1.getPriority() == o2.getPriority()) {
                    return 0;
                }
                return o1.getPriority() < o2.getPriority() ? -1 : 1;
            }
        });
    }


    public InvokerProxy(IConnectStrategy connectStrategy,int consumeTimeout,Class<?> targetInterface){
        this.connectStrategy = connectStrategy;
        this.consumeTimeout = consumeTimeout;
        this.targetInterface = targetInterface;
    }



    /**
     * 注意方法可能被并发调用
     * @param proxy
     * @param method
     * @param args
     * @return
     * @throws Throwable
     */
    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {

        ProviderService newProvider = connectStrategy.creatProvider(method);

        //声明调用Request对象,GengRequest表示发起一次调用所包含的信息
        final MyRequest request = new MyRequest();
        //设置本次调用的唯一标识
        request.setUniqueKey(UUID.randomUUID().toString() + "-" + Thread.currentThread().getId());
        //设置本次调用的服务提供者信息
        request.setProviderService(newProvider);
        //设置本次调用的超时时间
        request.setInvokeTimeout(consumeTimeout);
        //设置本次调用的方法名称
        request.setInvokedMethodName(method.getName());
        //设置本次调用的方法参数信息
        request.setArgs(args);


        MyResponse response = new MyResponse();
        //添加filter链
       FilterChain filterChain = new FilterChain(filterList);
       filterChain.doFilter(request,response);

       //获取结果
        MyResponse resultResponse = SendRequst.response;
        if(resultResponse == null) return null;
        return SendRequst.response.getResult();
    }



    public Object getProxy() {
        return Proxy.newProxyInstance(Thread.currentThread().getContextClassLoader(), new Class<?>[]{targetInterface}, this);
    }


    /**
     * 传入某种策略
     */
    public static InvokerProxy newInvokerProxyBeanFactory(IConnectStrategy connectStrategy,int consumeTimeout,Class<?> targetInterface) throws Exception {
        return new InvokerProxy(connectStrategy,consumeTimeout,targetInterface);
    }
}

